﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Statistics
{
    /// <summary>
    /// В этом классе описаны методы для расчета времени и качества проекта
    /// при известном распределении случайной величины, описывающей эти параметры
    /// </summary>
    public static class StatisticMath
    {
        /// <summary>
        /// Рассчитывает значение случайной величины в зависимости от функции, ее описывающей.
        /// </summary>
        /// <param name="d">Распределение - определяет вид функции</param>
        /// <param name="Coefs">Коэффициенты для расчета (список из не менее чем 5 элементов)</param>
        /// <returns>Положительная величина (время обработки проекта в блоке, качество проекта и т. д.)</returns>
        /// <param name="Q">Качество ресурса</param>
        /// <param name="C">Сложность проекта</param>
        /// <returns></returns>
        public static double Calculate(Distribution d, List<double> Coefs, double Q, double C)
        {
            double Var = 0;
            switch (d)
            {
                case Distribution.Normal:
                    if (Coefs[0] < 0)
                        throw new Exception("Мат. ожидание этой величины не может быть отрицательным!");
                    Var = Coefs[0] + Coefs[1] * RND(d) + Coefs[2] * Q +
                        (Coefs[3] + Coefs[4] * Q) * C;
                    break;
                default :
                    //добавить сюда код обработчика
                    break;
            }
            if (Var > 0)//обеспечим положительность возвращаемой величины
                return Var;
            else
                return 0.01;//некий эпсилон - минимальное время обработки проекта
        }
        /// <summary>
        /// Рассчитать значение СВ при заданном распределении
        /// </summary>
        /// <param name="d">Распределение</param>
        /// <param name="Coefs">Параметры распределения (список не менее чем из 2 элементов)</param>
        /// <returns>Положительная СВ</returns>
        public static double Calculate(Distribution d, List<double> Coefs)
        {
            double Var = 0;
            switch (d)
            {

                case Distribution.Normal:
                    if (Coefs[0] < 0)
                        throw new Exception("Мат. ожидание этой величины не может быть отрицательным!");
                    Var = Coefs[0] + Coefs[1] * RND(d);
                    break;
                default:
                    //добавить сюда код обработчика
                    break;
            }
            if (Var < 0) //обеспечим положительность возвращаемой величины
                return 0;
            else
                return Var;
        }
        private static double RND(Distribution distr)//случ. вел-на
        {
            Random r = new Random(DateTime.Now.Millisecond);
            double d = 0;
            switch (distr)
            {
                case Distribution.Normal://поулчим величину с мат. ожиданием 0 и дисперсией 1
                    int N = 10;
                    for (int i = 0; i < N; i++)
                    {
                        d += r.NextDouble();
                    }
                    //получили норм. распределенную вел-ну с M = N/2 и D = N/12;
                    d = (d - 0.5 * N) / Math.Sqrt(N / 12.0);
                    break;
                default :
                    //добавить сюда код обработчика
                    break;
            }
            return d;
        }
    }
}
